package encrypt

import (
	"crypto/md5"
	"encoding/base64"
	"encoding/hex"
	"encoding/json"
	"time"
)

type GenerateTokenRequest struct {
	AccessToken  string
	RefreshToken string
	UserId       int64
	Name         string
	Avatar       string
	TimeExpired  int64
}

type TokenResponse struct {
	Signature string
	GenerateTokenRequest
}

// 生成token
func GenerateToken(req *GenerateTokenRequest, salt string) (string, error) {
	var (
		signature string
		b         []byte
		err       error
	)
	signature, err = generateSignature(req, salt)

	if err != nil {
		return "", err
	}
	resp := &TokenResponse{
		Signature:            signature,
		GenerateTokenRequest: *req,
	}

	b, err = json.Marshal(resp)
	if err != nil {
		return "", err
	}
	return base64.StdEncoding.EncodeToString(b), nil
}

// 生成验证秘钥
func generateSignature(encryptBody *GenerateTokenRequest, salt string) (string, error) {
	var (
		b   []byte
		err error
	)
	b, err = json.Marshal(encryptBody)
	if err != nil {
		return "", err
	}

	b, err = AesEncrypt(b, []byte(salt))
	if err != nil {
		return "", err
	}

	m := md5.New()
	m.Write(b)

	return hex.EncodeToString(m.Sum(nil)), nil
}

// 验证签名
func CheckSignature(token string, salt string) *TokenResponse {
	s, err := base64.StdEncoding.DecodeString(token)
	if err != nil {
		return nil
	}
	var body TokenResponse
	if err := json.Unmarshal(s, &body); err != nil {
		return nil
	}

	// token已过有效期
	if body.TimeExpired < time.Now().Unix() {
		return nil
	}

	signature, err := generateSignature(&body.GenerateTokenRequest, salt)
	if err != nil {
		return nil
	}

	if body.Signature != signature {
		return nil
	}

	return &body
}
